﻿using System.Globalization;
using System.Text;
using Red.EngineData.View;
using System;

namespace Red.EngineData.Protocol.Interop
{
    /// <summary>
    /// Interop result translated from raw interop message
    /// </summary>
    public class InteropResult
    {
        public bool IsReadOnly;
        public string Type;
        public string Data;
        public string[] Children;
        public string[] Categories;
        public EInteropType InteropType;
    }

    /// <summary>
    /// Translate interop message from engine to editor's structures
    /// </summary>
    public class InteropParser
    {
        public comm.Message ConstructInterop( ulong expectedResponseID, string expression )
        {
            comm.InteropInvoke message = new comm.InteropInvoke();

            var bytes = Encoding.Unicode.GetBytes( expression );
            if ( bytes.Length != 0 )
            {
                message.expression.Add( Convert.ToByte( '.' ) );
                message.expression.AddRange( bytes );
            }

            message.expectedResponseID = expectedResponseID;

            return message;
        }

        public InteropResult ParseInteropResultMessage( comm.Message message )
        {
            if ( message.IsA( comm.EMessageID.InteropResponse ) == false )
                throw new ProtocolException( "Interop response parsing error: invalid message type. Type should be comm.InteropResponse.", null );

            comm.InteropResponse response = message as comm.InteropResponse;

            string str = System.Text.Encoding.ASCII.GetString( response.data.ToArray(), 0, response.data.Count );

            InteropResult result = new InteropResult()
            {
                IsReadOnly = response.isReadonly,
                Type = response.type,
                InteropType = (EInteropType)response.metaType,
                Data = str,
                Children = response.properties.ToArray(),
                Categories = response.categories.ToArray(),
            };

            return result;
        }

        public ulong ExtractResponseId( comm.Message message )
        {
            comm.InteropResponse response = message as comm.InteropResponse;
            return response.responseID;
        }

        public static string ConvertToUnicode( string text )
        {
            const int unicodeCodeLength = 6;

            StringBuilder sb = new StringBuilder();

            for ( int i = 0; i < text.Length; ++i )
            {
                if ( i + unicodeCodeLength <= text.Length )
                {
                    var token = text.Substring( i, unicodeCodeLength );
                    if ( token[0] == '&' && token[1] == '#' )
                    {
                        int charCode = 0;
                        if ( int.TryParse( token.Substring( 2 ), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out charCode ) )
                        {
                            var c = char.ConvertFromUtf32( charCode );
                            sb.Append( c );
                            i += ( unicodeCodeLength - 1 ); // -1 because next loop iteration add 1 to loop counter
                            continue;
                        }
                    }
                }
                sb.Append( text[i] );
            }

            return sb.ToString();
        }
    }
}
